#include "CCBoneTransform.h"
#include "CCBone.h"
#include "CCSpineGlobal.h"

NS_CC_BEGIN

CCBoneTransform::CCBoneTransform() {
}

CCBoneTransform::CCBoneTransform(CCBone* bone) :
_bone(bone) {
}

CCBoneTransform::~CCBoneTransform() {
}

CCBoneTransform* CCBoneTransform::create(CCBone* bone) {
	CCBoneTransform* bt = new CCBoneTransform(bone);
	return (CCBoneTransform*)bt->autorelease();
}

void CCBoneTransform::addRotationKeyFrame(const RotationKeyFrame& kf) {
	m_rkfList.push_back(kf);
}

void CCBoneTransform::addTranslationKeyFrame(const TranslationKeyFrame& kf) {
	m_tkfList.push_back(kf);
}

void CCBoneTransform::addScaleKeyFrame(const ScaleKeyFrame& kf) {
	m_skfList.push_back(kf);
}

void CCBoneTransform::populateFrame(float time, float deltaTime) {
	// process rotation frame
	{
		// set time to current time
        
		m_currentRotation.time = time;
		m_currentRotation.valid = true;
		
		// if empty, just set to zero
		// if not, found key frame, do interpolation if needed
		if(m_rkfList.empty()) {
			m_currentRotation.valid = false;
		} else {
			RotationKeyFrameList::iterator iter = m_rkfList.begin();
			for(; iter != m_rkfList.end(); iter++) {
				RotationKeyFrame& kf = *iter;
				if(time < kf.time) {
					if(iter == m_rkfList.begin()) {
						m_currentRotation.angle = kf.angle;
					} else {
						RotationKeyFrame& prevKf = *(iter - 1);
						float percent = getInterpolationTime(prevKf.time, kf.time, time, prevKf.interpolator);
						
						// simplifies rotation by rotating the shorter distance
						float prevAngle = prevKf.angle;
						float angle = kf.angle;
						
						// interpolate
                        float dx=(angle - prevAngle);
                        while (dx > 180)
                            dx -= 360;
                        while (dx < -180)
                            dx += 360;
						m_currentRotation.angle = percent * dx + prevAngle;
                        
					}
					break;
				} else if(time == kf.time) {
					m_currentRotation = kf;
                    
					break;
				}
			}
			
			// if exceed last one
			if(iter == m_rkfList.end()) {
				m_currentRotation.angle = m_rkfList.rbegin()->angle;
			}
		}
	}
	
	// process translation
	{
		// set time to current time
		m_currentTranslation.time = time;
		m_currentTranslation.valid = true;
		
		// if empty, just set to zero
		// if not, found key frame, do interpolation if needed
		if(m_tkfList.empty()) {
			m_currentTranslation.valid = false;
		} else {
			TranslationKeyFrameList::iterator iter = m_tkfList.begin();
			for(; iter != m_tkfList.end(); iter++) {
				TranslationKeyFrame& kf = *iter;
				if(time < kf.time) {
					if(iter == m_tkfList.begin()) {
						m_currentTranslation.x = kf.x;
						m_currentTranslation.y = kf.y;
					} else {
						TranslationKeyFrame& prevKf = *(iter - 1);
						float percent = getInterpolationTime(prevKf.time, kf.time, time, prevKf.interpolator);
						m_currentTranslation.x = percent * (kf.x - prevKf.x) + prevKf.x;
						m_currentTranslation.y = percent * (kf.y - prevKf.y) + prevKf.y;
                        
                        
					}
					break;
				} else if(time == kf.time) {
					m_currentTranslation = kf;
					break;
				}
                
			}
			
			// if exceed last one
			if(iter == m_tkfList.end()) {
				TranslationKeyFrame& kf = *m_tkfList.rbegin();
				m_currentTranslation.x = kf.x;
				m_currentTranslation.y = kf.y;
			}
		}
	}
	
	// process scale
	{
		// set time to current time
		m_currentScale.time = time;
		m_currentScale.valid = true;
		
		// if empty, just set to zero
		// if not, found key frame, do interpolation if needed
		if(m_skfList.empty()) {
			m_currentScale.valid = false;
		} else {
			ScaleKeyFrameList::iterator iter = m_skfList.begin();
			for(; iter != m_skfList.end(); iter++) {
				ScaleKeyFrame& kf = *iter;
				if(time < kf.time) {
					if(iter == m_skfList.begin()) {
						m_currentScale.scaleX = kf.scaleX;
						m_currentScale.scaleY = kf.scaleY;
					} else {
						ScaleKeyFrame& prevKf = *(iter - 1);
                        float percent = getInterpolationTime(prevKf.time, kf.time, time, prevKf.interpolator);
						m_currentScale.scaleX = percent * (kf.scaleX - prevKf.scaleX) + prevKf.scaleX;
						m_currentScale.scaleY = percent * (kf.scaleY - prevKf.scaleY) + prevKf.scaleY;
					}
					break;
				} else if(time == kf.time) {
					m_currentScale = kf;
					break;
				}
			}
			
			// if exceed last one
			if(iter == m_skfList.end()) {
				ScaleKeyFrame& kf = *m_skfList.rbegin();
				m_currentScale.scaleX = kf.scaleX;
				m_currentScale.scaleY = kf.scaleY;
			}
		}
	}
}

void CCBoneTransform::applyTo(CCSkeletalSprite* owner,float alpha) {
    
	
	// get state of this owner
    CCBone::State& state = _bone->getState(owner);
	
	// set rotation
	if(m_currentRotation.valid && !_bone->hasFlag(CCBone::FIXED_ROTATION)) {
        while (m_currentRotation.angle>180) {
            m_currentRotation.angle-=360;
        }
        while (m_currentRotation.angle<-180) {
            m_currentRotation.angle+=360;
        }
        state.rotation += m_currentRotation.angle*alpha;
	}
	
	// set translation
	if(m_currentTranslation.valid && !_bone->hasFlag(CCBone::FIXED_POSITION)) {
        state.x += m_currentTranslation.x*alpha;
        state.y += m_currentTranslation.y*alpha;
	}
	
	// set scale
	if(m_currentScale.valid && !_bone->hasFlag(CCBone::FIXED_SCALE)) {
        state.scaleX += (m_currentScale.scaleX-1)*alpha;
        state.scaleY += (m_currentScale.scaleY-1)*alpha;
	}
}

NS_CC_END